#include "message.hpp"
using std::cout;
using std::endl;
using std::string;
using std::vector;

using namespace zyb_rpc;
void t01()
{
    // RpcRequest::ptr
    BaseMessage::ptr rq = MessageFactory::create(MType::REQ_RPC);

    RpcResponse::ptr tmp = MessageFactory::create<RpcResponse>();
    BaseMessage::ptr bmp = MessageFactory::create<RpcRequest>();

    RpcRequest::ptr rrp = std::dynamic_pointer_cast<RpcRequest>(bmp);
    RpcResponse::ptr rp = std::dynamic_pointer_cast<RpcResponse>(bmp);
    if (rrp)
    {
        std::cout << "rrp Dynamic cast successful" << std::endl;
    }
    else
    {
        std::cout << "rrp Dynamic cast failed" << std::endl;
    }
    if (rp)
    {
        std::cout << "rp Dynamic cast successful" << std::endl;
    }
    else
    {
        std::cout << "rp Dynamic cast failed" << std::endl;
    }
}
void t02()
{

    RpcRequest::ptr rrq = MessageFactory::create<RpcRequest>();
    Json::Value param;
    param["num1"] = 11;
    param["num2"] = 22;
    rrq->setParams(param);
    rrq->setMethod("add");
    std::string str = rrq->serialize();
    cout << str << endl;
    BaseMessage::ptr bmp = MessageFactory::create(MType::REQ_RPC);
    bool ret = bmp->unserialize(str);
    cout << "ret: " << ret << endl;
    if (ret == false)
        return;
    ret = bmp->check();
    if (ret == false)
        return;
    RpcRequest::ptr rrp2 = std::dynamic_pointer_cast<RpcRequest>(bmp);
    cout << rrp2->method() << endl;
    cout << rrp2->params()["num1"] << endl;
    cout << rrp2->params()["num1"].asInt() << endl;
    cout << rrp2->params()["num2"].asInt() << endl;
}
void t03()
{
    TopicRequest::ptr trp = MessageFactory::create<TopicRequest>();

    trp->setTopicKey("news");
    trp->setOptype(TopicOptype::TOPIC_PUBLISH);
    trp->setTopicMsg("hello world");
    string str = trp->serialize();
    cout << str << endl;
    BaseMessage::ptr bmp = MessageFactory::create(MType::REQ_TOPIC);
    bool ret = bmp->unserialize(str);
    cout << "ret: " << ret << endl;
    if (ret == false)
        return;
    ret = bmp->check();
    if (ret == false)
        return;
    TopicRequest::ptr trp2 = std::dynamic_pointer_cast<TopicRequest>(bmp);
    cout << trp2->topicKey() << endl;
    cout << (int)trp2->optype() << endl;
    cout << trp2->topicMsg() << endl;
}
void t04()
{
    ServiceRequest::ptr trp = MessageFactory::create<ServiceRequest>();

    trp->setMethod("add");
    trp->setOptype(ServiceOptype::SERVICE_DISCOVERY);
    string str = trp->serialize();
    cout << str << endl;
    BaseMessage::ptr bmp = MessageFactory::create(MType::REQ_SERVICE);
    bool ret = bmp->unserialize(str);
    cout << "ret: " << ret << endl;
    if (ret == false)
        return;
    ret = bmp->check();
    if (ret == false)
        return;
    ServiceRequest::ptr trp2 = std::dynamic_pointer_cast<ServiceRequest>(bmp);
    cout << trp2->method() << endl;
    cout << (int)trp2->optype() << endl;
}
void t05()
{
    ServiceRequest::ptr trp = MessageFactory::create<ServiceRequest>();

    trp->setMethod("add");
    trp->setOptype(ServiceOptype::SERVICE_REGISTRY);
    trp->setHost({"127.0.0.1", 8888});
    string str = trp->serialize();
    cout << str << endl;
    BaseMessage::ptr bmp = MessageFactory::create(MType::REQ_SERVICE);
    bool ret = bmp->unserialize(str);
    cout << "ret: " << ret << endl;
    if (ret == false)
        return;
    ret = bmp->check();
    if (ret == false)
        return;
    ServiceRequest::ptr trp2 = std::dynamic_pointer_cast<ServiceRequest>(bmp);
    cout << trp2->method() << endl;
    cout << (int)trp2->optype() << endl;
    cout << trp2->host().first << endl;
    cout << trp2->host().second << endl;
}
void t06() // service response
{
    ServiceResponse::ptr trp = MessageFactory::create<ServiceResponse>();

    trp->setMethod("add");
    trp->setRCode(RCode::RCODE_OK);
    trp->setOptype(ServiceOptype::SERVICE_DISCOVERY);
    vector<Address> addrs = {{"127.0.0.1", 9090}, {"127.0.0.213", 8888}};
    trp->setHost(addrs);

    string str = trp->serialize();
    cout << str << endl;
    BaseMessage::ptr bmp = MessageFactory::create(MType::RSP_SERVICE);
    bool ret = bmp->unserialize(str);
    cout << "ret: " << ret << endl;
    if (ret == false)
        return;
    ret = bmp->check();
    if (ret == false)
        return;
    ServiceResponse::ptr trp2 = std::dynamic_pointer_cast<ServiceResponse>(bmp);
    cout << trp2->method() << endl;
    cout << (int)trp2->rcode() << endl;
    cout << (int)trp2->optype() << endl;
    for (auto &add : trp2->hosts())
        cout << add.first << ":" << add.second << endl;
}
void t07() // RPCResponse
{

    RpcResponse::ptr rrq = MessageFactory::create<RpcResponse>();
    Json::Value param;

    rrq->setRCode(RCode::RCODE_OK);
    rrq->setResult("add");
    std::string str = rrq->serialize();
    cout << str << endl;
    BaseMessage::ptr bmp = MessageFactory::create(MType::RSP_RPC);
    bool ret = bmp->unserialize(str);
    cout << "ret: " << ret << endl;
    if (ret == false)
        return;
    ret = bmp->check();
    if (ret == false)
        return;
    RpcResponse::ptr rrp2 = std::dynamic_pointer_cast<RpcResponse>(bmp);
    cout << (int)rrp2->rcode() << endl;
    cout << rrp2->result() << endl;
}
void t08() // topic response
{
    TopicResponse::ptr trp = MessageFactory::create<TopicResponse>();

    trp->setRCode(RCode::RCODE_OK);
    string str = trp->serialize();
    cout << str << endl;
    BaseMessage::ptr bmp = MessageFactory::create(MType::RSP_TOPIC);
    bool ret = bmp->unserialize(str);
    cout << "ret: " << ret << endl;
    if (ret == false)
        return;
    ret = bmp->check();
    if (ret == false)
        return;
    TopicResponse::ptr trp2 = std::dynamic_pointer_cast<TopicResponse>(bmp);
    cout << (int)trp2->rcode() << endl;
}
int main()
{
    cout << " ********test request*********\n";

    t01();
    cout << " *********************\n";
    t02();
    cout << " *********************\n";
    t03();
    cout << " *********************\n";
    t04();
    cout << " *********************\n";
    t05();
    cout << " ********test response*********\n";
    t06();
    cout << " *********************\n";
    t07();
    cout << " *********************\n";
    t08();
    return 0;
}
